package com.example.demo.controller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("/api")
public class GenericController {
    /**
     * 泛型
     *  泛型只在编译阶段有效。
     *  在编译过程中，正确检验泛型结果后，会将泛型的相关信息擦出，并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。
     *  不会进入运行阶段
     *  泛型有三种使用方式，分别为：
     *      泛型类、
     *          类型参数只能是类类型（包装类），不能是简单类型。
     *          不能对确切的泛型类型使用instanceof操作。ex_num instanceof Generic<Number> 错
     *          没有指定泛型类型，就是任意类型
     *      泛型接口、
     *      泛型方法
     *
     *  ? 泛型通配符  ?是类型实参，而不是类型形参
     *
     *  静态方法上不能直接调用类上的泛型，如果静态方法想实现泛型，必须定义成泛型方法形式
     *
     *  泛型上下边界 <T extends Number> T 或 <? extends Number> T
     *
     *  在java中 不能创建一个确切的泛型类型的数组
     *      List<String>[] ls = new ArrayList<String>[10]; 错误
     *      但是可以用通配符
     *      List<?>[] ls = new ArrayList<?>[10];
     *      或
     *      List<String>[] ls = new ArrayList[10];
     */

    // 1、 泛型类型
    @GetMapping("/class")
    public String genericClass() {
        GenericClass<String> genericClass = new GenericClass<>("泛型类");
        return genericClass.getKey();
    }

    // 2、泛型接口
    @GetMapping("/interface")
    public String genericInterface() {
        GenericInterfaceClass genericInterfaceClass = new GenericInterfaceClass();
        return genericInterfaceClass.getKey();
    }

    // 3、泛型方法
    @GetMapping("/method")
    public String genericMethod() {
        GenericMethod<String> method = new GenericMethod<>();
        return method.genericMethod("method");
    }

    // 4、可变参数
    @GetMapping("/variableMethod")
    public Object variableMethod() {
        GenericMethod<Integer> method = new GenericMethod<>();
        return method.variableMethod(1, 2, 3, 4, 4, 5, 5);
    }

    // 5、泛型上下界
    @GetMapping("/border")
    public Object genericBorder() {
        GenericBorder<Number> border = new GenericBorder<>();
        return border.getData(12);
    }

    // 泛型类
    private class GenericClass<T> {
        private T key;

        public GenericClass(T key) {
            this.key = key;
        }

        public T getKey() {
            return this.key;
        }
    }

    // 泛型接口
    private interface GenericInterface<T> {
        T getKey();
    }

    private class GenericInterfaceClass implements GenericInterface<String> {

        private String[] strList = new String[]{"apple", "vivo", "oppo"};

        @Override
        public String getKey() {
            Random rand = new Random();
            return strList[rand.nextInt(3)];
        }
    }

    // 泛型方法
    private class GenericMethod<T> {

        // 标准
        public <T> T genericMethod(T t) {
            return t;
        }

        // 可变参数
        public List<T> variableMethod(T ...t) {
            List<T> result = new ArrayList<>();
            for (T t1 : t) {
                result.add(t1);
            }
            return result;
        }
    }

    // 泛型上下界
    public class GenericBorder<T extends Number> {

        public <T extends Number> T getData(T t) {
            return t;
        }
    }
}
